﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;

namespace MirrorFolder
{
    public partial class FormMain : Form
    {
        const int yStep = 115;
        List<MirrorElement> ml = new List<MirrorElement>();

        string fPathSave;
        string dPathBackup;

        /// <summary>В данный момент идет выполнение одного из элементов</summary>
        bool SyncIsActive = false;

        public FormMain()
        {
            InitializeComponent();
            fPathSave = Application.StartupPath + "\\Data.db";
            Gl.DPathLogs = Application.StartupPath + "\\Logs";
            dPathBackup = Application.StartupPath + "\\Backup";
            if (!Directory.Exists(Gl.DPathLogs)) Directory.CreateDirectory(Gl.DPathLogs);
            if (!Directory.Exists(dPathBackup)) Directory.CreateDirectory(dPathBackup);

            LoadMirrorElements(fPathSave, false);

            /*FormSchedule frm = new FormSchedule();
            frm.ShowDialog(null);*/

            TestArchSnapshot();
        }

        void TestArchSnapshot()
        {
            /*DirSync.Snapshot sn = DirSync.GetArchSnapshot(@"D:\Тест Mirror\Архив\L07\FULL\", @"D:\Тест Mirror\Архив\L07\D_03\");
            Text = sn.DList.Count.ToString();*/

            /*List<DirSync.ArchiveLine> lines = DirSync.GetArchiveLines(@"D:\Тест Mirror\Архив", false);
            Text = lines.Count.ToString();*/

        }

        void LoadMirrorElements(string fPath, bool fromBackup)
        {
            try
            {
                if (File.Exists(fPath))
                {
                    using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(fPath)))
                    using (BinaryReader br = new BinaryReader(ms, Encoding.UTF8))
                    {
                        br.ReadByte();
                        MirrorElement.NextUIN = br.ReadInt32();
                        int len = br.ReadInt32();
                        for (int i = 0; i < len; i++)
                        {

                            MirrorElement el = new MirrorElement(br);
                            SetMirrorElement(el);
                            ml.Add(el);
                        }
                    }
                }
                btnAdd = new Button();
                btnAdd.Image = global::MirrorFolder.Properties.Resources.add_small;
                btnAdd.Name = "btnAdd";
                btnAdd.Size = new System.Drawing.Size(24, 24);
                btnAdd.TabIndex = 0;
                btnAdd.UseVisualStyleBackColor = true;
                btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
                RefillElements();

                if (!fromBackup) SaveBackup();
            }
            catch (Exception ex)
            {
                if (fromBackup) throw ex;
                if (MessageBox.Show("Ошибка загрузки данных. Восстановить данные из бэкапа?", "Восстановление данных", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.No) return;
                LoadBackup();
            }
        }

        void SaveMirrorElements()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8))
                {
                    bw.Write((byte)0);
                    bw.Write(MirrorElement.NextUIN);
                    bw.Write(ml.Count);
                    for (int i = 0; i < ml.Count; i++)
                    {
                        ml[i].SaveElement(bw);
                    }
                }
                File.WriteAllBytes(fPathSave, ms.ToArray());
            }

        }

        void SaveBackup()
        {
            if (File.Exists(fPathSave))
                File.Copy(fPathSave, dPathBackup + "\\DataBackup_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff") + ".db");
        }

        void LoadBackup()
        {
            string[] fl = Directory.GetFiles(dPathBackup, "*.db");
            List<FileInfo> fi = new List<FileInfo>();
            foreach (string f in fl) fi.Add(new FileInfo(f));
            fi.Sort((f1, f2) => f2.LastWriteTime.CompareTo(f1.LastWriteTime));

            foreach (FileInfo f in fi)
            {
                try
                {
                    LoadMirrorElements(f.FullName, true);
                    SaveMirrorElements();
                    MessageBox.Show("Данные восстановлены из бекапа от " + f.LastWriteTime.ToString("dd.MM.yyyy HH.mm.ss"));
                    return;
                }
                catch { File.Delete(f.FullName); }
            }
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            MirrorElement el = new MirrorElement();
            el = SetMirrorElement(el);
            ml.Add(el);
            SaveMirrorElements();
            RefillElements();
        }

        MirrorElement SetMirrorElement(MirrorElement el)
        {
            el.Tag = ml.Count;
            el.Delete += new EventHandler(mEl_Delete);
            el.ChangeData += new EventHandler(mEl_ChangeData);
            el.StartSync += new MirrorElement.StartSyncDelegate(mEl_StartSync);
            el.EndSync += new EventHandler(mEl_EndSync);
            return el;
        }

        #region *** события элементов *****************************************************

        void mEl_Delete(object sender, EventArgs e)
        {
            if (MessageBox.Show("Действительно удалить?", "Подтверждение удаления", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                return;
            int ind = (int)(sender as MirrorElement).Tag;
            ml[ind].Dispose();
            ml.RemoveAt(ind);
            SaveMirrorElements();
            RefillElements();
        }

        void mEl_ChangeData(object sender, EventArgs e)
        {
            SaveMirrorElements();
        }

        bool mEl_StartSync(object sender)
        {
            if (SyncIsActive) return false;
            SyncIsActive = true;
            return true;
        }

        void mEl_EndSync(object sender, EventArgs e)
        {
            SyncIsActive = false;
        }

        #endregion *** события элементов *****************************************************

        void RefillElements()
        {
            pnlElements.Controls.Clear();

            pnlElements.Height = ml.Count * yStep + 50;
            for (int i = 0; i < ml.Count; i++)
            {
                ml[i].Tag = i;
                ml[i].Left = 5;
                ml[i].Top = i * yStep + 5;
                pnlElements.Controls.Add(ml[i]);
            }
            btnAdd.Location = new System.Drawing.Point(730, (ml.Count) * yStep + 5);
            pnlElements.Controls.Add(btnAdd);
        }
    }
}
